В этом шаге мы посмотрим простенький пример работы с материалами.
Вообще-то понятие материала и источника света - это основа 3D графики (да и не только 3D, и не только графики ;) ).
Посмотрим каждый их них в отдельности:
Комбинаций свойств материала, источника света и окраски объекта может быть множество. В "Шаг 42 - Два источника света" мы задавали интенсивность источника света. Делали это так:
GLfloat light1_Intensity[4] = {1.0f, 1.0f, 1.0f, 1.0f};
Попробуйте теперь уменьшить красную составляющую на 1/2. Что получилось увидите сами. Объяснение простое. На источник света как бы наложен фильтр, который пропускает только свет определенного спектра.
Такая ситуация как предыдущая в природе случается редко. Как правило мы сталкиваемся с тем, что источник света белый (или близкий к нему, т.е. дневной свет), а вот материалы имеют разные свойства и потому мы видим их как бы определенного цвета (если они не окрашены). Пример - кирпич, он не крашенный, но имеет оранжевый цвет (я даже задумался ... цвет кирпича-то оранжевый? Наверное да, но в любом случае, правильный ответ - цвет зависит от свойств материала этого кирпича)
Вот теперь посмотрим тот же пример, но уже менять будем не свойства источника света, а свойства материала объекта. Для начала 2 глобальных переменных:
GLuint m_lstCube;
GLfloat m_matDiffuse[] = {0.0f, 0.0f, 0.0f};
Первая - это идентификатор списка, в котором будет содержаться куб. Второй - свойства материала рассеивать свет. Каждый элемент массива определяет рассеивает ли этот материал определенную длину волны света.
Теперь зададим это свойство:
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, m_matDiffuse);
Первая команда определяет так называемую модель освещения. Первый параметр может принимать два значения: GL_LIGHT_MODEL_TWO_SIDE и GL_LIGHT_MODEL_LOCAL_VIEWER. Первый определяет будет ли освещение расчитываться только для внешних граней или и для внешних и для внутренних, а второй - определяет как будет расчитываться угол отражения. Второй параметр задает значение для первого. Вторая команда собственно включает нам то самое свойство материала, которое мы ранее определили в массиве.
Вот и все. Свойства материала установлены, источник света включен. Все работает. Просто ради наглядности я добавил в обработчик от клавиатуры WM_KEYDOWN обработчики от кнопочек r,g,b.
Нажимая на них можно изименять свойство материала рассеивать ту или иную составляющую света.
case WM_KEYDOWN:
if(wParam == VK_ESCAPE) SendMessage(hWnd, WM_CLOSE, 0, 0);
if(wParam == 82) // r
{
if(red<=1.0f)
red += 0.1f;
else
red = 0.0f;
}
if(wParam == 71) // g
{
if(green <= 1.0f)
green += 0.1f;
else
green += 0.0f;
}
if(wParam == 66) // b
{
if(blue <= 1.0f)
blue += 0.1f;
else
blue = 0.0f;
}
if(wParam == 76) // l (можно отключить и включить источник света)
{
if(light)
{
light=FALSE;
glDisable(GL_LIGHTING);
glDisable(GL_LIGHT0);
} else {
light=TRUE;
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
}
}
if(wParam == 67) // c (можно включить или выключить окраску объекта)
{
if(color)
{
color=FALSE;
glEnable(GL_COLOR_MATERIAL);
} else {
color=TRUE;
glDisable(GL_COLOR_MATERIAL);
}
}
m_matDiffuse[0] = red;
m_matDiffuse[1] = green;
m_matDiffuse[2] = blue;
glMaterialfv(GL_FRONT, GL_DIFFUSE, m_matDiffuse);
break;
И еще одна маленькая деталь. Я немного поменял аргументы в команде установки вида:
GLvoid Resize(GLsizei w, GLsizei h)
{
if(w>=h)
glViewport ((w-h)/2, 0, (GLsizei) h, (GLsizei) h);
if(w<h)
glViewport (0, (h-w)/2, (GLsizei) w, (GLsizei) w);
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
glFrustum (-1, 1, -1, 1, 4, 15);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -12.0);
glRotatef(30.0, 1.0, 0.0, 0.0);
glRotatef(70.0, 0.0, 1.0, 0.0);
}
Теперь куб - это действительно куб, а не что-то параллелепипедное.
Забыл один небольшой, но важный момент. В тексте я писал слово рассеивать, очень хотелось написать слово отражать, но дело в том, что слово diffuse действительно переводится как рассеивать. По логике работы приложение, нажимая, например, на букву "r" мы как бы говорим OpenGL-ю, что наш материал НЕ БУДЕТ рассеиваить красный свет. У материала есть так же свойство отражения света, т.е. как бы качество полировки поверхности, поэтому не стоит путать diffuse со specular, но об этом в следующем шаге.